iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Mobile Development

在 Flutter 開發旅程的手札系列 第 26

Flutter Package — 用Agora製作通話功能(二)

  • 分享至 

  • xImage
  •  

今天要開始在Flutter的專案內使用Agora

下載套件

 flutter pub add agora_rtc_engine
 flutter pub add permission_handler

android 設定
開啟android->build.gradle

allprojects {
    repositories {
        maven { url 'https://www.jitpack.io' }
    }
}

https://ithelp.ithome.com.tw/upload/images/20221010/201526830xTSp2Kzr9.png

開啟android->app->src->main->AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <!-- The Agora SDK requires Bluetooth permissions in case users are using Bluetooth devices.-->
    <uses-permission android:name="android.permission.BLUETOOTH" />

https://ithelp.ithome.com.tw/upload/images/20221010/20152683MFTWTsTJPD.png


ios 設定

開啟ios->Runner->info.plist

	<key>NSCameraUsageDescription</key>
	<string>This app requires permission to access camera to scan qrcode</string>
	<key>NSMicrophoneUsageDescription</key>
	<string>This app requires permission to access microphone</string>

https://ithelp.ithome.com.tw/upload/images/20221010/20152683wSlgoX9UMa.png


取得appId
https://ithelp.ithome.com.tw/upload/images/20221010/20152683ydq8gcApcu.png

設定臨時的channel及token
https://ithelp.ithome.com.tw/upload/images/20221010/201526834ldmhVje8p.png


建立agora_screen.dart

我在這邊有特別將uid改為random的數值,讓大家能夠方便同時執行兩隻實體機有接通的畫面

import 'dart:math';

import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

const appId = "請輸入appId";
const token = "請輸入token";
const channel = "請輸入channel";

class AgoraScreen extends StatefulWidget {
  const AgoraScreen({Key? key}) : super(key: key);

  @override
  State<AgoraScreen> createState() => _AgoraScreenState();
}

class _AgoraScreenState extends State<AgoraScreen> {
  int? _remoteUid;
  bool _localUserJoined = false;
  late RtcEngine _engine;

  @override
  void initState() {
    super.initState();
    initAgora();
  }

  Future<void> initAgora() async {
    // retrieve permissions
    await [Permission.microphone, Permission.camera].request();

    //create the engine
    _engine = createAgoraRtcEngine();
    await _engine.initialize(const RtcEngineContext(
      appId: appId,
      channelProfile: ChannelProfileType.channelProfileLiveBroadcasting,
    ));

    _engine.registerEventHandler(
      RtcEngineEventHandler(
        onJoinChannelSuccess: (RtcConnection connection, int elapsed) {
          debugPrint("local user ${connection.localUid} joined");
          setState(() {
            _localUserJoined = true;
          });
        },
        onUserJoined: (RtcConnection connection, int remoteUid, int elapsed) {
          debugPrint("remote user $remoteUid joined");
          setState(() {
            _remoteUid = remoteUid;
          });
        },
        onUserOffline: (RtcConnection connection, int remoteUid, UserOfflineReasonType reason) {
          debugPrint("remote user $remoteUid left channel");
          setState(() {
            _remoteUid = null;
          });
        },
        onTokenPrivilegeWillExpire: (RtcConnection connection, String token) {
          debugPrint('[onTokenPrivilegeWillExpire] connection: ${connection.toJson()}, token: $token');
        },
      ),
    );

    await _engine.setClientRole(role: ClientRoleType.clientRoleBroadcaster);
    await _engine.enableVideo();
    await _engine.startPreview();
    Random random = Random();
    int uid = random.nextInt(100);
    await _engine.joinChannel(
      token: token,
      channelId: channel,
      uid: uid,
      options: const ChannelMediaOptions(),
    );
  }

  // Create UI with local view and remote view
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Agora Video Call'),
      ),
      body: Stack(
        children: [
          Center(
            child: _remoteVideo(),
          ),
          Align(
            alignment: Alignment.topLeft,
            child: SizedBox(
              width: 100,
              height: 150,
              child: Center(
                child: _localUserJoined
                    ? AgoraVideoView(
                        controller: VideoViewController(
                          rtcEngine: _engine,
                          canvas: const VideoCanvas(uid: 0),
                        ),
                      )
                    : const CircularProgressIndicator(),
              ),
            ),
          ),
        ],
      ),
    );
  }

  // Display remote user's video
  Widget _remoteVideo() {
    if (_remoteUid != null) {
      return AgoraVideoView(
        controller: VideoViewController.remote(
          rtcEngine: _engine,
          canvas: VideoCanvas(uid: _remoteUid),
          connection: const RtcConnection(channelId: channel),
        ),
      );
    } else {
      return const Text(
        'Please wait for remote user to join',
        textAlign: TextAlign.center,
      );
    }
  }
}



執行的時候要記得用實體機去跑,iPhone虛擬器無法模擬、Android的模擬器上會有奇怪的圖案

未接通Agora畫面
https://ithelp.ithome.com.tw/upload/images/20221011/20152683ZNT83Vvbpv.png

成功接通Agora畫面
https://ithelp.ithome.com.tw/upload/images/20221011/201526835mtOy5OCX9.png

兩支手機接通畫面
https://ithelp.ithome.com.tw/upload/images/20221011/201526830MXK7pk4dn.png


上一篇
Flutter Package — 用Agora製作視訊功能(一)
下一篇
Flutter Package - 如何使用dio在Proxyman抓封包(一)
系列文
在 Flutter 開發旅程的手札30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言